package cn.edu.fzu.homemaking.helper;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

public class UploadHelper {

    private static final Logger          logger           = LoggerFactory.getLogger(UploadHelper.class);

    private static final List<String>    FILE             = Arrays.asList("jpg", "png", "jpeg", "mp4");

    private static final String          UPLOAD_DIR       = "/mnt/fs/home-making/";

    private static final String          UPLOAD_LOCAL_DIR = UPLOAD_DIR + "local/";

    private static final String          FFMPEG_PATH      = "";

    private static final ExecutorService executorService  = Executors.newSingleThreadExecutor();

    /**
     * 上传到mfs
     **/
    public static String upload(String filename, MultipartFile multipartFile, String fileUrl) throws IOException {
        return fileUrl + upload(filename, UPLOAD_DIR, multipartFile);
    }


    /**
     * 上传到mfs的local目录
     **/
    public static String uploadLocal(String filename, MultipartFile multipartFile) throws IOException {
        return UPLOAD_LOCAL_DIR + upload(filename, UPLOAD_LOCAL_DIR, multipartFile);
    }


    /**
     * 上传
     **/
    private static String upload(String filename, String dir, MultipartFile multipartFile) throws IOException {
        if (!checkFile(multipartFile)) {
            throw new RuntimeException("文件格式不支持");
        }
        File file = new File(dir);
        if (!file.exists()) {
            file.mkdirs();
        }
        String dest = filename + "." + FilenameUtils.getExtension(multipartFile.getOriginalFilename());
        FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), new File(dir + dest));
        return dest;
    }


    private static boolean checkFile(MultipartFile file) {
        String extName = "";
        if (file.getOriginalFilename() != null) {
            extName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.') + 1);
        }
        return FILE.contains(extName.toLowerCase());
    }


    public static byte[] getFileFromUrl(String strUrl) {
        try {
            URL url = new URL(strUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            InputStream inStream = conn.getInputStream();
            return readInputStream(inStream);
        } catch (Exception e) {

        }
        return null;
    }


    /**
     * 从输入流中获取数据
     *
     * @param inStream 输入流
     * @return
     * @throws Exception
     */
    private static byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        try {
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outStream.write(buffer, 0, len);
            }
        } finally {
            if (inStream != null) {
                inStream.close();
            }
        }
        return outStream.toByteArray();
    }


    public static String getVideoType(String videoPath) {
        String ffmpegPath = FFMPEG_PATH;
        if (StringUtils.isBlank(ffmpegPath)) {
            //没有工具，则默认为H264格式视频
            return "MP4_H264";
        }
        String videoCommend = ffmpegPath + "ffmpeg  -i " + videoPath;

        try {
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec(videoCommend);
            InputStream stderr = proc.getErrorStream();
            InputStreamReader isr = new InputStreamReader(stderr);
            BufferedReader br = new BufferedReader(isr);
            String line = null;
            while ((line = br.readLine()) != null) {
                if (line.contains("hevc")) {
                    return "MP4_HEVC";
                } else if (line.contains("mpeg4")) {
                    return "MP4_MPEG4";
                } else if (line.contains("h264")) {
                    return "MP4_H264";
                }
            }
        } catch (Exception e) {
            logger.error("parse video error", e);
            throw new RuntimeException("视频文件解析失败");
        }
        return null;
    }


    public static String transferVideoToMfs(String videoType, String localFilePath) {
        File localFile = new File(localFilePath);
        //将本地视频剪切到云服务目录
        String destFileUrl = localFilePath.replace("/local", "");
        localFile.renameTo(new File(destFileUrl));

        String destUrl = destFileUrl;
        if (!"MP4_H264".equals(videoType)) {
            destUrl = destFileUrl.replace(".mp4", "_h264_.mp4");
            transfer(destFileUrl, destUrl);
        }
        return UPLOAD_DIR + destUrl;
    }


    /** 将视频转码为h264 **/
    public static void transfer(String inputFileUrl, String outputFileUrl) {

        String ffmpegPath = FFMPEG_PATH;
        if (StringUtils.isBlank(ffmpegPath)) {
            //将原来视频名字更换为目标文件名
            new File(inputFileUrl).renameTo(new File(outputFileUrl));
            return;
        }

        executorService.submit(new Runnable() {
            @Override
            public void run() {
                boolean success = false;
                String videoCommend = ffmpegPath + "ffmpeg -i " + inputFileUrl + " -vcodec libx264 " + outputFileUrl;
                try {
                    Runtime rt = Runtime.getRuntime();
                    Process proc = rt.exec(videoCommend);
                    InputStream stderr = proc.getErrorStream();
                    InputStreamReader isr = new InputStreamReader(stderr);
                    BufferedReader br = new BufferedReader(isr);
                    String line = null;
                    while ((line = br.readLine()) != null) {
                        logger.debug(line);
                    }
                    int exitVal = proc.waitFor();
                    if (exitVal == 0) {
                        success = true;
                    }
                } catch (Exception e) {
                    logger.error("transfer video error.", e);
                }
                File inputFile = new File(inputFileUrl);
                if (success) {
                    //转码成功，则将转码前的视频删除
                    inputFile.delete();
                } else {
                    //转码失败，则将原来视频名字更换为转码后的文件名
                    File outputFile = new File(outputFileUrl);
                    if (outputFile.exists()) {
                        outputFile.delete();
                    }
                    inputFile.renameTo(outputFile);
                }
            }
        });
    }

}
